package org.javahispano.javacup.tacticas_aceptadas.jpautom.org.javahispano.javacup.tacticas.pitufos;
import java.awt.Color;
import java.util.*;
import org.javahispano.javacup.modelo.*;
//import org.javahispano.javacup.EVDepurador;
//import org.javahispano.javacup.EVDepuradorCreator;

public class Pitufos implements Tactica{
	PitufosDetalle detalle=new PitufosDetalle();

	public TacticaDetalle getDetalle() {
		return detalle;
	}

	public Posicion[] getPosicionSaca(SituacionPartido sp) {
		Posicion p[] = new Posicion[11];
		double d=Constantes.DISTANCIA_SAQUE;
		double d2=Constantes.LARGO_CAMPO_JUEGO/2;
		double d3=Constantes.ANCHO_CAMPO_JUEGO/2;

		p[0]=new Posicion(0, -d2*3/4);
		p[1]=new Posicion(-d, -d2/4);
		p[2]=new Posicion(0, -d2/4);
		p[3]=new Posicion(d, -d2/4);

		p[4]=new Posicion(-d3/4, 0);
		p[5]=new Posicion(d3/4, 0);
		p[6]=new Posicion(-d3/2, 0);
		p[7]=new Posicion(d3/2, 0);

		p[8]=new Posicion(-d/2, 0);
		p[9]=new Posicion(d/2, 0);
		p[10]=new Posicion(0, 0);

		return p;
	}

	public Posicion[] getPosicionRecive(SituacionPartido sp) {
		Posicion p[] = new Posicion[11];
		if (sp.iteracion()==0) {
			for (int i=2; i<11; i++) {
				double ang=Math.PI/8;
				p[i]=new Posicion(Constantes.DISTANCIA_SAQUE*Math.cos(Math.PI+(i-2)*ang), Constantes.DISTANCIA_SAQUE*Math.sin(Math.PI+(i-2)*ang));
				p[1]=new Posicion(0, -2*Constantes.DISTANCIA_SAQUE);
				p[0]=new Posicion(0, -Constantes.LARGO_CAMPO_JUEGO/3);
			}
		}
		else {
			double d=Constantes.DISTANCIA_SAQUE;
			double d2=Constantes.LARGO_CAMPO_JUEGO/2;
			double d3=Constantes.ANCHO_CAMPO_JUEGO/2;
			p[0]=new Posicion(0, -d2*3/4);
			p[1]=new Posicion(-d, -d2/2);
			p[2]=new Posicion(0, -d2/2);
			p[3]=new Posicion(d, -d2/2);
			p[4]=new Posicion(-d3/2, 0);
			p[5]=new Posicion(d*Math.cos(5*Math.PI/4), d*Math.sin(5*Math.PI/4));
			p[6]=new Posicion(d*Math.cos(7*Math.PI/4), d*Math.sin(7*Math.PI/4));
			p[7]=new Posicion(d3/2, 0);
			p[8]=new Posicion(-d, 0);
			p[9]=new Posicion(d, 0);
			p[10]=new Posicion(0, -d);
		}
		return p;
	}

	Historia hist=new Historia();
	Estadistica stats=new Estadistica();
	Campo campoActual;
	//EVDepurador deb;
	boolean primeraVez=true;

	public List<Comando> ejecutar(SituacionPartido sp) {
		if (primeraVez) {
			inicializarPrimeraVez();
			primeraVez=false;
		}
		//debugAll(sp);
		updateAll(sp);
		Analisis an=new Analisis(campoActual);
		Vector comandos=new Vector<Comando>();

		if (an.getValPosesion1()>0.5) {
			// Ataque
			comandos.addAll(ataqueCircular(campoActual, an));
			comandos.addAll(vibrar(campoActual, an));
			comandos.addAll(masCercanoPorBalon(campoActual, an));
		}
		else {
			// Defensa
			comandos.addAll(defensa2008(campoActual, an));
			comandos.addAll(masCercanoPorBalonDefensivo(campoActual, an));
		}
		comandos.addAll(portero(campoActual, an));

		Pase p=new Pase();
		p.setCampo((Campo)campoActual.clone());
		p.ejecutar();
		comandos.addAll(p.getComandos());

		Tiro t=new Tiro();
		t.setCampo((Campo)campoActual.clone());
		t.ejecutar();
		comandos.addAll(t.getComandos());




//		debugFuturoBola(campoActual);
		return comandos;
	}

	private List<Comando> porteroVago(SituacionPartido sp) {
		Vector comandos=new Vector<Comando>();
		for (int i=0; i<sp.puedenRematar().length; i++) {
			if (sp.puedenRematar()[i]==0) {
				ComandoGolpearBalon c=new ComandoGolpearBalon(0, 90, 1.0, 39);
				comandos.add(c);
			}
		}
		double xdest=sp.balon().getX();
		xdest=Math.min(xdest, Constantes.LARGO_ARCO/2-Constantes.DISTANCIA_CONTROL_BALON_PORTERO);
		xdest=Math.max(xdest, -Constantes.LARGO_ARCO/2+Constantes.DISTANCIA_CONTROL_BALON_PORTERO);
		ComandoIrA cia=new ComandoIrA(0, new Posicion(xdest, -Constantes.LARGO_CAMPO_JUEGO/2));
		comandos.add(cia);

		return comandos;
	}

	private List<Comando> vibrar(Campo c, Analisis an) {
		Vector comandos=new Vector<Comando>();

		if (an.getTPosesion()==1) {
			for (int i=0; i<11; i++) {
				double ang=Math.random()*2*Math.PI;
				double v=c.getInfo().getV(i);
				Pos p=(Pos)c.getJugador(i).getPos().clone();
				p.setLocation(p.x+v*Math.cos(ang), p.y+v*Math.sin(ang));
				comandos.add(Util.crearComandoIrA(c, i, p));
			}
		}
		return comandos;
	}
	private List<Comando> portero(Campo c, Analisis an) {
		Vector comandos=new Vector<Comando>();

		Pos destino;
		if (an.getNJPosesion()==1 && an.getJPosesion()[0]==0) {
			destino=an.getPosPosesion();
		}
		else {
			Pos poste1=new Pos(-Constantes.LARGO_ARCO/2+Constantes.RADIO_BALON, -Constantes.LARGO_CAMPO_JUEGO/2, 0);
			Pos poste2=new Pos( Constantes.LARGO_ARCO/2-Constantes.RADIO_BALON, -Constantes.LARGO_CAMPO_JUEGO/2, 0);
			Pos b=an.getPosPosesion();
			double d1=b.distance2d(poste1);
			double d2=b.distance2d(poste2);
			Pos porteria=new Pos(poste1.x+Math.abs(poste2.x-poste1.x)*d1/(d1+d2), -Constantes.LARGO_CAMPO_JUEGO / 2, 0.0);

			double phi1=Util.angulo(b, poste1);
			double phi2=Util.angulo(b, poste2);

			double phi=(phi1+phi2)/2;

			int jPeligro=11;
			double dPeligro=porteria.distance2d(c.getJugador(jPeligro).getPos());
			for (int i=12; i<22; i++) {
				double d=porteria.distance2d(c.getJugador(i).getPos());
				if (d<dPeligro) {
					dPeligro=d;
					jPeligro=i;
				}
			}
			double d=Math.max(2*Constantes.LARGO_CAMPO_JUEGO/3, b.distance2d(c.getJugador(jPeligro).getPos()));
			d=Math.min(d, b.distance2d(porteria));

			destino=new Pos(b);
			destino.setLocation(destino.x+Math.cos(phi)*d, destino.y+Math.sin(phi)*d);
		}
		comandos.add(Util.crearComandoIrA(c, 0, destino));
		return comandos;
	}


	private List<Comando> todosMenosPorteroPorBalon(Campo c) {
		Vector comandos=new Vector<Comando>();
		for (int i=0; i<11; i++) {
			if (!c.getInfo().isPortero(i)) {
				Pos p=new Pos();
				Util.intercepcion(c, i, p);
				comandos.add(new ComandoIrA(i, new Posicion(p.getX(), p.getY())));
			}
		}

		return comandos;
	}

	private List<Comando> masCercanoPorBalon(Campo c, Analisis an) {
		Vector comandos=new Vector<Comando>();
		int[] jugs=an.getJPosesion();
		for (int i=0; i<jugs.length; i++) {
			if (jugs[i]<11) { 
				comandos.add(Util.crearComandoIrA(c, jugs[i], an.getPosPosesion()));
			}
		}
		return comandos;
	}

		private List<Comando> masCercanoPorBalonDefensivo(Campo c, Analisis an) {
		Vector comandos=new Vector<Comando>();
		int minT=an.getTIntercepcion(0);
		int minJ=0;
		for (int i=1; i<11; i++) {
			if (an.getTIntercepcion(i)<minT) {
				minT=an.getTIntercepcion(i);
				minJ=i;
			}
		}
		comandos.add(Util.crearComandoIrA(c, minJ, Util.getPosDesplazadaDefensa(an.getPosPosesion(), 0.5)));
		return comandos;
	}



	private List<Comando> defensa2008(Campo c, Analisis an) {
		Vector comandos=new Vector<Comando>();

		int[] jugs=new int[10];
		for (int i=0; i<jugs.length; i++) jugs[i]=i+1;
		ArrayList<Pos> peligrosos=new ArrayList<Pos>();
		for (int j=11; j<22; j++) {
			peligrosos.add(c.getJugador(j).getPos());
		}
		Pos porteria=new Pos(0, -Constantes.LARGO_CAMPO_JUEGO/2, 0);
		Collections.sort(peligrosos, new ComparadorPeligro(porteria, an.getPosPosesion()));
		Pos[] poss=new Pos[peligrosos.size()];
		peligrosos.toArray(poss);
		Pos[] destino=Util.matchPriority(c, jugs, poss);

		for (int i=0; i<jugs.length; i++) {
			if (destino[i]!=null) {
				comandos.add(Util.crearComandoIrA(c, jugs[i], destino[i]));
			}
		}
		return comandos;
	}

	private class ComparadorPeligro implements Comparator<Pos> {
		private Pos pos1, pos2;

		public ComparadorPeligro(Pos pos1, Pos pos2) {
			this.pos1=pos1; this.pos2=pos2;
		}
		public int compare(Pos p1, Pos p2) {
			double d1=pos1.distance2dSq(p1);
			double d2=pos1.distance2dSq(p2);
			if (d1<d2) return -1;
			else if (d1>d2) return 1;
			else
				return (int)Math.round(pos2.distance2dSq(p1)-pos2.distance2dSq(p2));

		}
	}


	private List<Comando> ataqueCircular(Campo c, Analisis an) {
		Vector comandos=new Vector<Comando>();
		int[] jugs=new int[10];
		Pos[] poss=new Pos[10];
		Pos b=c.getBola().getPos();
		double radio=Constantes.ANCHO_CAMPO_JUEGO/3;
		double bordeX=Constantes.ANCHO_CAMPO_JUEGO/2-Constantes.ANCHO_CAMPO_JUEGO/10;
		double bordeY=Constantes.LARGO_CAMPO_JUEGO/2-Constantes.LARGO_CAMPO_JUEGO/10;

		for (int i=0; i<jugs.length; i++) {
			jugs[i]=i+1;
			poss[i]=new Pos(b);
			poss[i].x=poss[i].x+radio*Math.cos(i*2*Math.PI/poss.length);
			if (Math.abs(poss[i].x)>bordeX) poss[i].x=Math.signum(poss[i].x)*(2*bordeX-Math.abs(poss[i].x));
			poss[i].y=poss[i].y+radio*Math.sin(i*2*Math.PI/poss.length);
			if (Math.abs(poss[i].y)>bordeY) poss[i].y=Math.signum(poss[i].y)*(2*bordeY-Math.abs(poss[i].y));
		}
		Pos[] destino=Util.match(c, jugs, poss);

		for (int i=0; i<jugs.length; i++) {
			if (destino[i]!=null) {
				comandos.add(Util.crearComandoIrA(c, jugs[i], destino[i]));
			}
		}

		return comandos;
	}


	private void updateAll(SituacionPartido sp) {
		hist.update(sp);
		campoActual=hist.getCampo(0);
		stats.update(sp);
	}

	private void inicializarPrimeraVez() {
		//deb=EVDepuradorCreator.crearInstancia(Color.YELLOW);
	}

//	private void debugFuturoBola(Campo c) {
//		Campo.Bola b=(Campo.Bola)c.getBola().clone();
//		while (Util.dentroCampo(b.getPos()) && b.getMov().getR()>0.1) {
//			//Util.log("b=%s\n", b.toString());
//			Util.futuroBola(b, 1);
//			if (b.getPos().getZ()>Constantes.ALTO_ARCO)
//				deb.circ(b.getPos(), Constantes.RADIO_BALON, 1, Color.RED);
//			else if (b.getPos().getZ()>Constantes.ALTURA_CONTROL_BALON)
//				deb.circ(b.getPos(), Constantes.RADIO_BALON, 1, Color.PINK);
//			else
//				deb.circ(b.getPos(), Constantes.RADIO_BALON, 1);
//		}
//	}

//	private void debugAll(SituacionPartido sp) {
//		Util.log("%4d: ", sp.iteracion());
//		Util.log("b[%.2f,%.2f,%.2f]  ", sp.balon().getX(), sp.balon().getY(), sp.alturaBalon());
//		for (int i=0; i<11; i++) {
//			Util.log("%2d[%.2f,%.2f] ", i, sp.misJugadores()[i].getX(), sp.misJugadores()[i].getY());
//		}
//		Util.log(" || ");
//		for (int i=0; i<11; i++) {
//			Util.log("%2d[%.2f,%.2f] ", i, sp.misJugadores()[i].getX(), sp.rivales()[i].getY());
//		}
//		Util.log("\n");
//	}

}
